<template>
  <Card>
    <Form :label-col="{ xs: { span: 4 }, md: { span: 3 }, lg: { span: 2 } }">
      <FormItem label="SPU名称" v-bind="validateInfos.spuName">
        <Input v-model:value="spu.spuName" placeholder="请输入spu名称" />
      </FormItem>

      <FormItem label="SPU品牌" v-bind="validateInfos.tmId">
        <!-- Tip: 要指定宽度才能看到 -->
        <Select v-model:value="spu.tmId" placeholder="请选择spu品牌" class="spu-select">
          <SelectOption v-for="tm in trademarkList" :key="tm.id" :value="tm.id">
            {{ tm.tmName }}
          </SelectOption>
        </Select>
      </FormItem>

      <FormItem label="SPU描述" v-bind="validateInfos.description">
        <Textarea
          v-model:value="spu.description"
          placeholder="请输入spu描述"
          :auto-size="{ minRows: 2, maxRows: 5 }"
        />
      </FormItem>

      <FormItem label="SPU图片" v-bind="validateInfos.spuImageList">
        <Upload
          list-type="picture-card"
          v-model:file-list="imageList"
          @preview="handlePreview"
          :action="`${apiUrl}/admin/product/fileUpload`"
          :before-upload="beforeUpload"
          @change="handleChange"
        >
          <div v-if="imageList.length < 10">
            <plus-outlined />
            <div class="ant-upload-text">上传图片</div>
          </div>
          <div></div>
        </Upload>
        <Modal :visible="previewVisible" :footer="null" @cancel="previewVisible = false">
          <img alt="previewImage" style="width: 100%" :src="previewImage" />
        </Modal>
      </FormItem>

      <FormItem label="销售属性" v-bind="validateInfos.spuSaleAttrList">
        <Select
          v-model:value="saleAttrName"
          :placeholder="`还剩${filterBaseSaleAttrList.length}个销售属性`"
          class="spu-select"
        >
          <SelectOption
            v-for="saleAttr in filterBaseSaleAttrList"
            :key="saleAttr.id"
            :value="saleAttr.name"
          >
            {{ saleAttr.name }}
          </SelectOption>
        </Select>
        <Button type="primary" @click="addSaleAttr" :disabled="!saleAttrName" class="save-spu-btn">
          <template #icon> <PlusOutlined /> </template>
          添加销售属性
        </Button>

        <Table :data-source="spu.spuSaleAttrList" :pagination="false" rowKey="index" bordered>
          <TableColumn key="index" title="序号" width="80px" align="center">
            <template #default="{ index }">
              <span>
                {{ index + 1 }}
              </span>
            </template>
          </TableColumn>

          <TableColumn
            key="saleAttrName"
            title="销售属性名称"
            width="120px"
            data-index="saleAttrName"
          />
          <TableColumn
            key="spuSaleAttrValueList"
            title="销售属性值列表"
            data-index="spuSaleAttrValueList"
          >
            <template #default="{ record, index }">
              <Tag
                v-for="(saleAttrValue, i) in record.spuSaleAttrValueList"
                :key="saleAttrValue.id"
                closable
                color="blue"
                @close="record.spuSaleAttrValueList.splice(i, 1)"
                class="save-spu-tag"
              >
                {{ saleAttrValue.saleAttrValueName }}
              </Tag>
              <Input
                v-if="record.isEdit"
                v-model:value="saleAttrValueName"
                :ref="
                  (el) => {
                    if (el) inputs[index] = el;
                  }
                "
                @blur="addSaleAttrValue(record)"
                placeholder="请输入销售属性值"
                class="save-spu-input"
              />
              <Button v-else @click="showEdit(record, index)">
                <template #icon> <PlusOutlined /> </template>
                添加销售属性值
              </Button>
            </template>
          </TableColumn>
          <TableColumn key="oprator" title="操作" width="100px">
            <template #default="{ index }">
              <Tooltip placement="top">
                <template #title>
                  <span>删除SKU</span>
                </template>
                <Button type="primary" danger @click="spu.spuSaleAttrList.splice(index, 1)">
                  <template #icon> <DeleteOutlined /> </template>
                </Button>
              </Tooltip>
            </template>
          </TableColumn>
        </Table>
      </FormItem>

      <FormItem>
        <Button type="primary" @click.prevent="onSubmit">确认</Button>
        <Button class="save-spu-btn" @click="emits('setIsShow', 1)">取消</Button>
      </FormItem>
    </Form>
  </Card>
</template>

<script lang="ts" setup>
  import { reactive, ref, computed, onMounted, nextTick } from 'vue';
  import {
    Card,
    Form,
    FormItem,
    Input,
    Select,
    SelectOption,
    Textarea,
    Upload,
    Modal,
    message,
    Button,
    Table,
    TableColumn,
    Tooltip,
    Tag,
  } from 'ant-design-vue';
  import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
  import { useGlobSetting } from '/@/hooks/setting';
  import { FileItem, FileInfo } from '../../form';
  import { SpuItem, baseSaleAttrListModel, SpuSaleAttrItem } from '/@/api/product/model/spuModel';
  import { trademarkListModel } from '/@/api/product/model/trademarkModel';
  import {
    getBaseSaleAttrListApi,
    saveSpuApi,
    updateSpuApi,
    getSpuImageListApi,
    getSpuSaleAttrListApi,
  } from '/@/api/product/spu';
  import { getAllTrademarkListApi } from '/@/api/product/trademark';
  import { useCategoryStore } from '/@/store/modules/category';

  const emits = defineEmits(['setIsShow']);
  const props = defineProps({
    currentSpu: {
      type: Object,
      required: true,
    },
  });

  // 获取请求地址前缀（参考axios的baseURL获取方式）
  const apiUrl = useGlobSetting().apiUrl;

  const categoryStore = useCategoryStore();
  const useForm = Form.useForm;

  const spu = reactive<SpuItem>(props.currentSpu as SpuItem);

  // select的placeholder属性，当值为undefined才会显示
  // 选中的销售属性名
  const saleAttrName = ref<string | undefined>(undefined);
  // 输入的销售属性值
  const saleAttrValueName = ref<string>('');

  const rules = reactive({
    spuName: [{ required: true, message: '请输入spu名称' }],
    tmId: [{ required: true, message: '请选择spu品牌' }],
    description: [{ required: true, message: '请输入spu描述' }],
    spuImageList: [{ required: true, message: '请上传spu图片', type: 'array' }],
    spuSaleAttrList: [{ required: true, message: '请添加spu销售属性', type: 'array' }],
  });

  const { validateInfos, validate } = useForm(spu, rules);

  // 图片数据
  const imageList = computed(() => {
    return spu.spuImageList.map((img) => {
      return {
        uid: img.uid || img.id,
        name: img.imgName,
        url: img.imgUrl,
      };
    });
  });

  const previewVisible = ref<boolean>(false);
  const previewImage = ref<string | undefined>('');

  // 图片预览
  const handlePreview = (file: FileItem) => {
    previewImage.value = file.response && file.response.data ? file.response.data : file.thumbUrl;
    previewVisible.value = true;
  };

  // 上传图片时触发
  const handleChange = ({ fileList }: FileInfo) => {
    // 必须不断更新
    spu.spuImageList = fileList.map((file) => {
      return {
        imgName: file.name,
        imgUrl: file.url || file.response?.data,
        uid: file.uid,
        status: file.status,
      };
    });
  };

  // 上传图片之前触发
  const beforeUpload = (file: FileItem) => {
    // 对上传图片的类型和大小进行限制
    const fileTypes = ['image/jpeg', 'image/jpg', 'image/png'];

    const isValidFileType = fileTypes.includes(file.type);
    const isValidFileSize = file.size / 1024 < 500;

    if (!isValidFileType) {
      message.error('上传头像图片只能是 JPG 或 PNG 格式!');
    }
    if (!isValidFileSize) {
      message.error('上传头像图片大小不能超过 500KB!');
    }

    // 返回值true，通过，可以上传图片
    // 返回值false，不通过，不会上传图片
    return isValidFileType && isValidFileSize;
  };

  // 发送请求，获取数据
  const baseSaleAttrList = ref<baseSaleAttrListModel>([]);
  const trademarkList = ref<trademarkListModel>([]);

  onMounted(async () => {
    const { id } = spu;

    let promises: Promise<any>[] = [getBaseSaleAttrListApi(), getAllTrademarkListApi()];

    if (id) {
      promises = promises.concat([getSpuImageListApi(id), getSpuSaleAttrListApi(id)]);
    }

    const [
      baseSaleAttrListResponse,
      trademarkListResponse,
      spuImageListResponse,
      spuSaleAttrListResponse,
    ] = await Promise.all(promises);

    baseSaleAttrList.value = baseSaleAttrListResponse;
    trademarkList.value = trademarkListResponse;
    if (id) {
      spu.spuImageList = spuImageListResponse;
      spu.spuSaleAttrList = spuSaleAttrListResponse.map((item, index) => {
        return {
          index,
          item,
        };
      });
    }
  });

  const filterBaseSaleAttrList = computed(() => {
    return baseSaleAttrList.value.filter((baseSaleAttr) => {
      return !spu.spuSaleAttrList.find((saleAttr) => saleAttr.saleAttrName === baseSaleAttr.name);
    });
  });

  // 添加销售属性
  const addSaleAttr = () => {
    if (saleAttrName.value) {
      spu.spuSaleAttrList.push({
        // 查找baseSaleAttr的id
        baseSaleAttrId: baseSaleAttrList.value.find(
          (saleAttr) => saleAttr.name === saleAttrName.value,
        )?.id,
        // 销售属性名
        saleAttrName: saleAttrName.value,
        // 销售属性值列表
        spuSaleAttrValueList: [],
        isEdit: false,
        index: spu.spuSaleAttrList.length + 1,
      });
    }

    // select的placeholder属性，当值为undefined才会显示
    // 为了清空select选中值
    saleAttrName.value = undefined;
  };

  const inputs = ref<HTMLInputElement[]>([]);

  // 显示编辑模式
  const showEdit = async (saleAttr: SpuSaleAttrItem, index: number) => {
    saleAttr.isEdit = true;
    await nextTick();
    inputs.value[index].focus();
  };

  // 添加销售属性值
  const addSaleAttrValue = (saleAttr: SpuSaleAttrItem) => {
    if (saleAttrValueName.value) {
      // 添加
      // 销售属性值列表
      saleAttr.spuSaleAttrValueList.push({
        baseSaleAttrId: saleAttr.baseSaleAttrId,
        saleAttrValueName: saleAttrValueName.value, // 销售属性值名称
      });
      // 清空输入框数据
      saleAttrValueName.value = '';
    }
    // 显示模式
    saleAttr.isEdit = false;
  };

  // 提交表单
  const onSubmit = () => {
    validate().then(async () => {
      const { category3Id } = categoryStore;
      const { id } = spu;
      if (id) {
        await updateSpuApi({
          ...spu,
          category3Id,
        });
      } else {
        await saveSpuApi({
          ...spu,
          category3Id,
        });
      }
      emits('setIsShow', 1);
      message.success(`${id ? '更新' : '添加'}SPU成功`);
    });
  };
</script>

<style scoped>
  .spu-select {
    width: 200px;
  }

  .save-spu-input {
    width: 200px;
  }

  .save-spu-tag {
    margin-right: 10px;
  }

  .save-spu-btn {
    margin-left: 20px;
    margin-bottom: 20px;
  }
</style>
